﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
using YiYiTong.Rocket.Model;
using YiYiTong.Rocket.Helper;

namespace YiYiTong.Rocket.Business
{
    /// <summary>
    /// 微信app支付
    /// </summary>
    public class WechatBiz
    {
        /// <summary>
        /// 微信统一下单
        /// tuple item1 是否成功 item2 成功返回token_id item3失败返回错误原因
        /// </summary>
        /// <returns></returns>
        public static Tuple<bool, string, string> BuildOrder(string orderId, decimal amt)
        {
            //组织请求参数
            WxReqModel model = new WxReqModel();
            model.appid = ConfigHelper.AppSetting<string>("wx_appid");
            model.mch_id = ConfigHelper.AppSetting<string>("wx_mchid");
            model.nonce_str = Utils.GetRandomCode(30);
            model.body = "爱电子-充值";
            model.out_trade_no = orderId;
            model.total_fee = ConvertHelper.ConvertTo<int>(amt * 100); //总金额，单位分
            model.spbill_create_ip = Utils.GetClientIP();
            model.notify_url = ConfigHelper.AppSetting<string>("wx_notifyurl");
            model.trade_type = "APP";

            Hashtable ht = ModelHandler<WxReqModel>.TransforClass(model);
            string key = ConfigHelper.AppSetting<string>("wx_md5key");
            string sign = Utils.CreateSign(ht, key);
            model.sign = sign;

            //解析请求数据
            string postData = Utils.ToXml(model);
            string url = ConfigHelper.AppSetting<string>("wx_posturl");
            LogHelper.Info("微信统一下单,请求数据：" + postData);

            string result = HttpHelper.HttpPost(url, postData, "application/xml");
            LogHelper.Info("微信统一下单,响应数据：" + result);
            if (!string.IsNullOrEmpty(result))
            {
                Hashtable retHt = Utils.StrToXml(result);
                string returnCode = Utils.GetHtValue(retHt, "return_code");
                string returnMsg = Utils.GetHtValue(retHt, "return_msg");
                //验证响应
                if (Utils.CheckSign(retHt, key))
                {
                    string resultCode = Utils.GetHtValue(retHt, "result_code");
                    if (resultCode == "SUCCESS" && returnCode == "SUCCESS")
                    {
                        string prepayid = Utils.GetHtValue(retHt, "prepay_id");
                        string payData = Pay(model.appid, model.mch_id, prepayid, key);
                        return new Tuple<bool, string, string>(true, payData, "");
                    }
                    else
                        return new Tuple<bool, string, string>(false, "", returnMsg);
                }
                else
                    return new Tuple<bool, string, string>(false, "", returnMsg);
            }
            else
                return new Tuple<bool, string, string>(false, "", "请求无响应");
        }

        /// <summary>
        /// 调起支付（组织支付参数给app调用）
        /// </summary>
        /// <param name="prepayid"></param>
        private static string Pay(string appid, string mchid, string prepayid, string key)
        {
            WechatPayModel model = new WechatPayModel();
            model.appid = appid;
            model.partnerid = mchid;
            model.prepayid = prepayid;
            model.package = "Sign=WXPay";
            model.noncestr = Utils.GetRandomPwd(30);
            model.timestamp = Utils.GetTimeStamp().ToString();

            Hashtable ht = ModelHandler<WechatPayModel>.TransforClass(model);
            string sign = Utils.CreateSign(ht, key);
            model.sign = sign;

            return JsonHelper.Serialize(model);
        }

        /// <summary>
        /// 微信查询订单
        /// tuple item1 是否成功 item2 成功返回订单model对象 item3失败返回错误原因
        /// </summary>
        /// <param name="orderId"></param>
        /// <returns></returns>
        public static Tuple<bool, WxOrderModel, string> QueryOrder(string orderId)
        {
            Hashtable ht = new Hashtable();
            ht.Add("appid", ConfigHelper.AppSetting<string>("wx_appid"));
            ht.Add("mch_id", ConfigHelper.AppSetting<string>("wx_mchid"));
            ht.Add("nonce_str", Utils.GetRandomPwd(30));
            ht.Add("out_trade_no", orderId);

            string key = ConfigHelper.AppSetting<string>("wx_md5key");
            string sign = Utils.CreateSign(ht, key);
            ht.Add("sign", sign);

            string postData = Utils.ToXml(ht);
            string url = ConfigHelper.AppSetting<string>("wx_queryurl");
            LogHelper.Info("微信查询订单,请求数据：" + postData);

            string result = HttpHelper.HttpPost(url, postData, "application/xml");
            LogHelper.Info("微信查询订单,响应数据：" + result);
            if (!string.IsNullOrEmpty(result))
            {
                Hashtable retHt = Utils.StrToXml(result);
                string returnCode = Utils.GetHtValue(retHt, "return_code");
                string returnMsg = Utils.GetHtValue(retHt, "return_msg");
                //验证响应
                if (Utils.CheckSign(retHt, key))
                {
                    string resultCode = Utils.GetHtValue(retHt, "result_code");
                    if (resultCode == "SUCCESS" && returnCode == "SUCCESS")
                    {
                        WxOrderModel model = new WxOrderModel();
                        model.orderAmt = ConvertHelper.ConvertTo<int>(Utils.GetHtValue(retHt, "total_fee"));
                        model.orderId = Utils.GetHtValue(retHt, "out_trade_no");
                        model.sellOrderId = Utils.GetHtValue(retHt, "transaction_id");
                        model.tradeState = Utils.GetHtValue(retHt, "trade_state");

                        return new Tuple<bool, WxOrderModel, string>(true, model, "");
                    }
                    else
                        return new Tuple<bool, WxOrderModel, string>(false, null, returnMsg);
                }
                else
                    return new Tuple<bool, WxOrderModel, string>(false, null, returnMsg);
            }
            else
                return new Tuple<bool, WxOrderModel, string>(false, null, "请求无响应");
        }

        /// <summary>
        /// 退款申请
        /// </summary>
        /// <param name="orderId">订单号</param>
        /// <param name="amt">订单总金额</param
        /// <param name="refundAmt">退款金额</param>
        /// <returns></returns>
        public static Tuple<bool, string> Refund(string refundOrderId, string orderId, decimal amt, decimal refundAmt)
        {
            string mch_id = ConfigHelper.AppSetting<string>("wx_mchid");
            Hashtable ht = new Hashtable();
            ht.Add("appid", ConfigHelper.AppSetting<string>("wx_appid"));
            ht.Add("mch_id", mch_id);
            ht.Add("nonce_str", Utils.GetRandomPwd(30));
            ht.Add("out_trade_no", orderId);
            ht.Add("out_refund_no", refundOrderId);
            ht.Add("total_fee", ConvertHelper.ConvertTo<int>(amt * 100));
            ht.Add("refund_fee", ConvertHelper.ConvertTo<int>(refundAmt * 100));
            ht.Add("notify_url", ConfigHelper.AppSetting<string>("wx_refund_notifyurl"));

            string key = ConfigHelper.AppSetting<string>("wx_md5key");
            string sign = Utils.CreateSign(ht, key);
            ht.Add("sign", sign);

            string postData = Utils.ToXml(ht);
            string url = ConfigHelper.AppSetting<string>("wx_refundurl");
            LogHelper.Info("微信退款申请,请求数据：" + postData);

            string result = HttpHelper.WechatPost(url, postData, ConfigHelper.AppSetting<string>("wx_cert_path"), mch_id);
            LogHelper.Info("微信退款申请,响应数据：" + result);
            if (!string.IsNullOrEmpty(result))
            {
                Hashtable retHt = Utils.StrToXml(result);
                string returnCode = Utils.GetHtValue(retHt, "return_code");
                string returnMsg = Utils.GetHtValue(retHt, "return_msg");
                //验证响应
                //if (Utils.CheckSign(retHt, key))
                //{
                string resultCode = Utils.GetHtValue(retHt, "result_code");
                if (resultCode == "SUCCESS" && returnCode == "SUCCESS")
                    return new Tuple<bool, string>(true, "");
                else
                    return new Tuple<bool, string>(false, returnMsg);
                //}
                //else
                //    return new Tuple<bool, string>(false, returnMsg);
            }
            else
                return new Tuple<bool, string>(false, "请求无响应");
        }

////        public static Tuple<bool, string> Test()
////        {
////            string mch_id = ConfigHelper.AppSetting<string>("wx_mchid");
////            string key = ConfigHelper.AppSetting<string>("wx_md5key");

////            string result = @"<xml><return_code><![CDATA[SUCCESS]]></return_code>
////<return_msg><![CDATA[OK]]></return_msg>
////<appid><![CDATA[wx782fa789e5770cf5]]></appid>
////<mch_id><![CDATA[1241528102]]></mch_id>
////<nonce_str><![CDATA[71eNrprIQ7PB4jNB]]></nonce_str>
////<sign><![CDATA[5B818EC6FEA09C793FE590434FFDF420]]></sign>
////<result_code><![CDATA[SUCCESS]]></result_code>
////<transaction_id><![CDATA[4200000290201906107490704727]]></transaction_id>
////<out_trade_no><![CDATA[19061013325074671415]]></out_trade_no>
////<out_refund_no><![CDATA[T1906101407250580]]></out_refund_no>
////<refund_id><![CDATA[50000700722019061009850233888]]></refund_id>
////<refund_channel><![CDATA[]]></refund_channel>
////<refund_fee>5</refund_fee>
////<coupon_refund_fee>0</coupon_refund_fee>
////<total_fee>5</total_fee>
////<cash_fee>5</cash_fee>
////<coupon_refund_count>0</coupon_refund_count>
////<cash_refund_fee>5</cash_refund_fee>
////</xml>	";
////            Hashtable retHt = Utils.StrToXml(result);
////            string returnCode = Utils.GetHtValue(retHt, "return_code");
////            string returnMsg = Utils.GetHtValue(retHt, "return_msg");
////            //验证响应
////            if (Utils.CheckSign(retHt, key))
////            {
////                string resultCode = Utils.GetHtValue(retHt, "result_code");
////                if (resultCode == "SUCCESS" && returnCode == "SUCCESS")
////                    return new Tuple<bool, string>(true, "");
////                else
////                    return new Tuple<bool, string>(false, returnMsg);
////            }
////            return new Tuple<bool, string>(false, "");
////        }
    }
}
